﻿using System;

namespace Utilities
{
    public sealed class Tuple<TA, TB> : IEquatable<Tuple<TA, TB>>
        where TA : class
        where TB : class
    {
        private readonly TA m_One;
        private readonly TB m_Two;

        public Tuple(TA one, TB two)
        {
            if (one == null) throw new ArgumentNullException("one");
            if (two == null) throw new ArgumentNullException("two");
            m_One = one;
            m_Two = two;
        }

        public TA One
        {
            get { return m_One; }
        }

        public TB Two
        {
            get { return m_Two; }
        }

        public bool Equals(Tuple<TA, TB> other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return Equals(other.m_One, m_One) && Equals(other.m_Two, m_Two);
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (Tuple<TA, TB>)) return false;
            return Equals((Tuple<TA, TB>) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                return (m_One.GetHashCode()*397) ^ m_Two.GetHashCode();
            }
        }

        public static bool operator ==(Tuple<TA, TB> left, Tuple<TA, TB> right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(Tuple<TA, TB> left, Tuple<TA, TB> right)
        {
            return !Equals(left, right);
        }
    }
}
